home *** CD-ROM | disk | FTP | other *** search
- /*
- * $RCSfile: serverInfo.C,v $
- * $Revision: 1.2 $
- * $Date: 1996/05/04 23:51:44 $
- */
- /**********************************************************************
- * EXODUS Database Toolkit Software
- * Copyright (c) 1991 Computer Sciences Department, University of
- * Wisconsin -- Madison
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
- * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.
- * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
- * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * The EXODUS Project Group requests users of this software to return
- * any improvements or extensions that they make to:
- *
- * EXODUS Project Group
- * c/o David J. DeWitt and Michael J. Carey
- * Computer Sciences Department
- * University of Wisconsin -- Madison
- * Madison, WI 53706
- *
- * or exodus@cs.wisc.edu
- *
- * In addition, the EXODUS Project Group requests that users grant the
- * Computer Sciences Department rights to redistribute these changes.
- **********************************************************************/
-
- #include "Pool.h"
- #include "HashTable.h"
- #include "resources.h"
-
- #include "sysdefs.h"
- #include "ess.h"
- #include "checking.h"
- #include "trace.h"
- #include "error.h"
- #include "list.h"
- #include "tid.h"
- #include "io.h"
- #include "lock.h"
- #include "object.h"
- #include "msgdefs.h"
- #include "host.h"
- #include "bf.h"
- #include "serverinfo.h"
- #include "bitvec.h"
- #include "link.h"
- #include "chunk.h"
- #include "lsn.h"
- #include "loginfo.h"
- #include "volume.h"
- #include "softwareVersion.h"
- #include "bf_extfuncs.h"
- #include "msg_funcs.h"
- #include "msg_globals.h"
- #include "sm_globals.h"
- #include "util_funcs.h"
- #include "sm_state.h"
- #include "trans_funcs.h"
- #include "trans_globals.h"
- #include "io_extfuncs.h"
- #include "clog.h"
- #include "bf_macro.h"
- #include "clog_extfuncs.h"
-
- class SOCKADDRCLASS {
- public:
- SOCKADDR p;
- int hashFunc() const {
- #if defined(hpux) || defined(sgi) || defined(linux)
- return (int)(this->p.sin_addr.s_addr);
- #else
- return (int)(this->p.sin_addr.S_un.S_addr);
- #endif
- }
- BOOL equalFunc (SOCKADDRCLASS *other) const {
- return ((this->p.sin_family == other->p.sin_family) &&
- (this->p.sin_port == other->p.sin_port) &&
- #if defined(hpux) || defined(sgi) || defined(linux)
- (this->p.sin_addr.s_addr == other->p.sin_addr.s_addr));
- #else
- (this->p.sin_addr.S_un.S_addr == other->p.sin_addr.S_un.S_addr));
- #endif
- }
- };
-
- void
- SERVERINFO::Init() {
- this->ReInit();
- initializeListElement(&(this->list), this);
- initializeList(&(this->transList));
- bzero(this->hostName, sizeof(this->hostName));
- this->hostEnt = NULL;
- bzero(this->name, sizeof(this->name));
- bzero((char *)&(this->connectAddr), sizeof(this->connectAddr));
- }
-
- /* ReInit called on pool->Get() -- AND explicitly on disconnect!
- * We NEVER put serverInfos back into the pool!
- */
- void
- SERVERINFO:: ReInit() {
- if(this->logInfo.tailBuffer != NULL) {
- /* true only when server disconnects an inactive client after a timeout.
- SM_ASSERT(LEVEL_1, (PAGE_IS_CLEAN(this->logInfo.tailBuffer)));
- */
- this->logInfo.tailBuffer = NULL;
- }
- this->socket = NOSOCKET;
-
- /*
- * old way: this->flags = SERV_NOTCONNECTED;
- * new way: turn off all flags except SERV_CONTACTED_IN_PAST
- */
- this->flags = (this->flags & SERV_CONTACTED_IN_PAST) | SERV_NOTCONNECTED;
- /* SERV_NOTCONNECTED is zero so this is for readability only */
-
- this->logInfo.writeGroup = NULL;
- this->logInfo.page2size = 0;
- this->nMounted = 0;
- }
-
- SOCKADDRCLASS *
- SERVERINFO::keylocation(int unique, SOCKADDRCLASS **unused) {
- TRPRINT(TR_TRANS, TR_LEVEL_1, (" ", unique));
- SM_ASSERT(LEVEL_1,
- (unique == SERVERINFO_POOL) || (unique == SERVERINFO_TABLE));
- return (SOCKADDRCLASS *)&(this->connectAddr);
- }
- LISTELEMENT *
- SERVERINFO::listlocation(int unique) {
- TRPRINT(TR_TRANS, TR_LEVEL_1, (" ", unique));
- SM_ASSERT(LEVEL_1,
- (unique == SERVERINFO_POOL) || (unique == SERVERINFO_TABLE));
- return &(this->list);
- }
- BOOL
- SERVERINFO::Dump(FILE *f) {
- fprintf(f, "SERVERINFO for %s.%d (%s)\n",
- inet_ntoa(this->connectAddr.sin_addr),
- this->connectAddr.sin_port,
- this->hostName);
- fprintf(f, "\tsocket %d, %d volumes mounted, flags 0x%x\n",
- this->socket, this->nMounted, this->flags);
- fprintf(f, "\tloggingEnabled %d\n",
- this->flags & SERV_LOGGING_INITD);
- return FALSE;
- }
-
-
- Pool<SERVERINFO> *serverInfoPool = NULL;
- HashTable<SOCKADDRCLASS,SERVERINFO> *serverInfoTable = NULL;
- static char localHostName[MAX_HOSTNAME];
-
- static BOOL initialized = FALSE;
-
- int
- initServerInfo()
- {
- if(initialized)
- return esmNOERROR;
-
- TRACE(TR_MSG, TR_LEVEL_1);
-
- serverInfoPool = new Pool<SERVERINFO> ( "serverInfo",
- SERVERINFO_POOL, ServerInfoPoolSize, POOL_NOMORE_GETMORE );
- if(serverInfoPool == NULL) {
- SM_ERROR(TYPE_SYS, esmMALLOCFAILED);
- return esmFAILURE;
- }
- /*
- serverInfoPool->Stats(stderr);
- */
-
- serverInfoTable = new HashTable<SOCKADDRCLASS,SERVERINFO> (
- "serverInfoTable", SERVERINFO_TABLE, ServerInfoTableSize);
- if(serverInfoTable == NULL) {
- SM_ERROR(TYPE_SYS, esmMALLOCFAILED);
- return esmFAILURE;
- }
- /*
- serverInfoTable->Stats(stderr);
- */
-
- if (gethostname(localHostName, MAX_HOSTNAME) < 0) {
- SM_ERROR(TYPE_SYS, errno);
- return esmFAILURE;
- }
- initialized = TRUE;
- return esmNOERROR;
- }
-
- void
- shutServerInfo()
- {
- if( !initialized )
- return;
-
- TRACE(TR_MSG, TR_LEVEL_1);
-
- serverForEach(1, detectedDisconnect, 0,0,0 );
-
- delete serverInfoPool;
- delete serverInfoTable;
-
- initialized = FALSE;
- }
-
- SERVERINFO*
- getServerInfo (
- char* serverHost, /* name of the machine running sm_server */
- char* serverName /* /etc/services port name of the sm_server*/
- )
- {
- SERVENT *_servent= NULL;
- HOSTENT *_hostent= NULL;
- SERVERINFO *serverInfo;
- SOCKADDRCLASS sockaddrc;
- short port;
-
- TRACE(TR_MSG, TR_LEVEL_1);
-
- if(!initialized)
- initServerInfo();
-
- if (serverHost == NULL) {
- serverHost = localHostName;
- }
- if(strlen(serverHost)>MAX_HOSTNAME) {
- serverHost[MAX_HOSTNAME-1] = '\0';
- }
- TRPRINT(TR_MSG, TR_LEVEL_1, ("looking up host:%s", serverHost));
-
- if(isalpha(*serverHost)) {
- if ((_hostent = gethostbyname(serverHost)) == NULL) {
- SM_ERROR(TYPE_USER, esmUNKNOWNHOSTNAME);
- return NULL;
- }
- bcopy( _hostent->h_addr,
- (char *) &(sockaddrc.p.sin_addr), _hostent->h_length );
- TRPRINT(TR_MSG, TR_LEVEL_1, ("official host name:%s", _hostent->h_name));
- } else {
- #if defined(hpux) || defined(sgi) || defined(linux)
- sockaddrc.p.sin_addr.s_addr = inet_addr(serverHost);
- /* returned net byte order*/
- if( sockaddrc.p.sin_addr.s_addr == (unsigned long) -1) {
- SM_ERROR(TYPE_USER, esmUNKNOWNHOSTNAME);
- return NULL;
- }
- #else
- sockaddrc.p.sin_addr.S_un.S_addr = inet_addr(serverHost);
- /* returned net byte order*/
- if( sockaddrc.p.sin_addr.S_un.S_addr == (unsigned long) -1) {
- SM_ERROR(TYPE_USER, esmUNKNOWNHOSTNAME);
- return NULL;
- }
- #endif
- }
-
- /*
- * get the server name, using the one provided, or if that's null,
- * the default, SERVENAME
- */
- if (!strcmp(serverName,""))
- strcpy(serverName, SERVENAME);
-
- if(strlen(serverName)>MAX_HOSTNAME) {
- serverName[MAX_HOSTNAME-1] = '\0';
- }
-
- /*
- * If the server name starts with digit, treat it as a port number.
- */
- if(isdigit(serverName[0])) {
- port = htons((short)(atoi(serverName)));
- if(port==0) {
- SM_ERROR(TYPE_LOG, EADDRNOTAVAIL);
- return NULL;
- }
- } else if ((_servent = getservbyname(serverName, "tcp")) != NULL) {
- TRPRINT(TR_MSG, TR_LEVEL_1,
- ("port:%d", ntohs(_servent->s_port)));
- /* returned in network byte order */
- port = (short) _servent->s_port;
- } else {
- SM_ERROR(TYPE_LOG, EADDRNOTAVAIL);
- return NULL;
- }
-
- /*
- * initialize the address
- */
- sockaddrc.p.sin_family = AF_INET;
- sockaddrc.p.sin_port = port;
- TRPRINT(TR_MSG, TR_LEVEL_1, ("host inet addr:%s:%d",
- inet_ntoa(*(struct in_addr *)&sockaddrc.p.sin_addr),
- ntohs(sockaddrc.p.sin_port)));
-
- serverInfo = serverInfoTable->Find(&sockaddrc);
- if(serverInfo==NULL) {
- serverInfo = serverInfoPool->Get();
- strcpy(serverInfo->hostName, serverHost);
- strcpy(serverInfo->name, serverName);
- serverInfo->connectAddr = sockaddrc.p;
- serverInfoTable->Insert(serverInfo);
- }
- return serverInfo;
- }
-
-
- SERVERINFO *
- findServerInfo (
- VOLID volid
- )
- {
- /* TODO: have THIS fun put the volrec into the SM_State -
- * need to pass in a ptr so we aren't doing so many
- * find volid lookups
- */
- VOLREC *volRec;
-
- TRPRINT(TR_IO, TR_LEVEL_1, ("volid:%d", volid));
-
- volRec = io_FindVolId(volid);
- if (volRec == NULL) {
- return NULL;
- }
-
- return volRec->serverInfo;
- }
-
- int
- server_beginTrans(
- SERVERINFO *serverInfo,
- TID *tidp
- )
- {
- TID tid;
- int error;
-
- TRACE(TR_SM|TR_TRANS, TR_LEVEL_1);
-
- INIT_SMSTATE(&SM_State);
-
- if ( !(serverInfo->flags & SERV_ESTAB) ) {
- SM_ERROR(TYPE_USER, esmNOTCONNECTED);
- }
- if (error = beginTrans(serverInfo, &tid)) {
- return error;
- }
-
- /*
- * First we need to set the server state so that lower
- * levels know what server to talk to. This is a temporary
- * hack to do this.
- */
- SM_State.serverInfo = serverInfo;
- SM_State.serverTid = tid;
- SM_State.logInfo = &(serverInfo->logInfo);
- SM_State.logLevel = LOG_ALL;
- SM_State.defaultLogLevel = LOG_ALL;
-
- /* set up logging for the transaction */
- if (error = (int)clog_BeginTransaction()) {
- return error ;
- }
- if(tidp)
- *tidp = tid;
- return esmNOERROR;
- }
-
- void
- serverForEach(
- int nargs,
- void *func,
- void *arg1,
- void *arg2,
- void *arg3,
- void *arg4,
- void *arg5,
- void *arg6
- )
- {
- SM_ASSERT(LEVEL_1, (nargs <= 7));
- SM_ASSERT(LEVEL_1, (nargs >= 1));
-
- #ifdef __GNUC__
- serverInfoTable->ForEach(nargs,func,arg1,arg2,arg3,arg4,arg5,arg6);
- #else __GNUC__
- serverInfoTable->ForEach(nargs,(FOREACHFUNC)func,arg1,
- arg2,arg3,arg4,arg5,arg6);
- #endif __GNUC__
- }
-
- int
- msg_initClient (
- SERVERINFO *serverInfo,
- BOOL isAdminClient
- )
- {
-
- if ( !(serverInfo->flags & SERV_ESTAB) ) {
- MESSAGE message;
-
- /* get initialization information from the server */
- message.header.type = INIT_CLIENT;
- message.header.replyRequested = TRUE;
-
- message.body.init.slottedPage2size = SLOTTED_PAGE2SIZE ;
- message.body.init.lgPage2size = LG_PAGE2SIZE ;
- message.body.init.lgDataPage2size = LGDATA_PAGE2SIZE ;
- message.body.init.btreePage2size = BTREE_PAGE2SIZE ;
- message.body.init.indexDescPage2size = INDEXDESC_PAGE2SIZE ;
- message.body.init.minPage2size = MIN_PAGE2SIZE ;
- message.body.init.softwareVersion = SOFTWARE_VERSION ;
-
- if (callServer(serverInfo, &message, NULL, 0 ) != esmNOERROR) {
- extern int PrintUser;
- if( PrintUser) {
- if( message.body.init.softwareVersion != SOFTWARE_VERSION) {
- fprintf(stderr,
- "Client version is incompatible with server version.\n");
- } else {
- fprintf(stderr,
- "Client page sizes do not match server page sizes\n");
- }
- }
- return esmFAILURE;
- }
- serverInfo->logInfo.volid = message.body.init.volid;
- serverInfo->logInfo.page2size = message.body.init.logPage2size;
- serverInfo->logInfo.initLRCisLSN = message.body.init.initLRCisLSN;
- serverInfo->flags |= SERV_ESTAB;
-
- if(serverInfo->logInfo.tailBuffer != NULL) {
- SM_ASSERT(LEVEL_1,
- (serverInfo->logInfo.tailBuffer->hashList.hashPid.volid
- == serverInfo->logInfo.volid));
- }
- }
-
- if(isAdminClient)
- return esmNOERROR;
-
- if (clog_serverInitialize(serverInfo)) {
- return esmFAILURE;
- }
-
- return esmNOERROR;
- }
-
- int
- server_connectInit (
- SERVERINFO *serverInfo,
- BOOL isAdminClient /* true if this is called from an administrative
- function (has no log or buffer pool) */
- )
- {
-
- if (!(serverInfo->flags & SERV_CONNECTED)) {
- if (connectServer(serverInfo) == esmFAILURE) {
- return esmFAILURE;
- }
- }
- if (msg_initClient(serverInfo,isAdminClient) != esmNOERROR ) {
- detectedDisconnect(serverInfo);
- return esmFAILURE;
- }
- return esmNOERROR;
- }
-
- int
- connectInit (
- char *serverHost, /* name of machine running sm_server */
- char *serverName, /* /etc/services name of the sm_server */
- BOOL isAdminClient /* true if this is called from an administrative
- function (has no log or buffer pool) */
- )
- {
- SERVERINFO *serverInfo;
-
- serverInfo = getServerInfo( serverHost, serverName);
-
- if (serverInfo->flags & SERV_ESTAB) {
- SM_ERROR(TYPE_USER, esmALREADYCONNECTED);
- return esmFAILURE;
- }
- return server_connectInit(serverInfo, isAdminClient);
- }
-
- #ifdef JUNK
- /* not used at the moment */
- static BOOL
- helperfunc(
- TRANSREC *transRec,
- SERVERINFO *serverInfo
- )
- {
- SERVERTRANSREC *stl;
-
- for(stl = (SERVERTRANSREC *)FIRST_LIST_ELEMENT(&(transRec->participants));
- stl!=NULL;
- stl = (SERVERTRANSREC *)NEXT_LIST_ELEMENT(&(stl->participants)) ) {
-
- if( stl->serverInfo == serverInfo ) {
- CLIENT_ABORT_TRANS(transRec);
- }
- }
- return FALSE;
- }
- #endif JUNK
-
- BOOL
- detectedDisconnect (
- SERVERINFO *serverInfo
- )
- {
- if(serverInfo->flags & SERV_CONNECTED) {
- SM_ASSERT(LEVEL_1, (serverInfo->socket != NOSOCKET));
- serverAbortedTrans(serverInfo, NULL_TID);
- serverDied((void *) serverInfo);
-
- /* record the reason for the abort */
- sm_reason = esmNOTCONNECTED;
-
- if (close(serverInfo->socket) != 0) {
- SM_ERROR(TYPE_LOG, errno);
- }
-
- /*
- * clear the link
- */
- clearLink(&(Links[serverInfo->socket]));
- } else {
- SM_ASSERT(LEVEL_1, (serverInfo->socket == NOSOCKET));
- SM_ASSERT(LEVEL_1,
- ((serverInfo->flags & ~SERV_CONTACTED_IN_PAST) == SERV_NOTCONNECTED));
- }
-
- /* only if the group was opened: */
- if( serverInfo->logInfo.writeGroup != NULL )
- (void) bf_DiscardGroup(serverInfo->logInfo.writeGroup);
-
- serverInfo->ReInit();
-
- return FALSE; /* used in forEach, so it must be BOOL */
- }
-
- int
- initMask()
- {
- int i;
-
- for (i = 0; i < BVL; i++) {
- SelectMask.bv_data[i] = 0;
- }
- return esmNOERROR;
- }
-